# -*- coding: utf-8 -*-
"""
统一判重处理模块
整合网络件和来信件的判重逻辑，消除代码重复
"""

import json
import requests
from typing import Dict, List, Optional, Union
from llm import quick_chat
from prompts import get_system_prompt
from .config import LLM_CONFIG, USE_SILICONFLOW
from .clean_llm_result import clean_llm_result


class UnifiedDuplicateChecker:
    """统一判重检查器"""

    def __init__(self):
        self.api_url = "http://156.22.1.35:6065/api/v1/dmx/xfcfj"
        self.timeout = 30

    def extract_bfyrs_from_case(self, case_instruction: str) -> List[Dict[str, str]]:
        """
        通过模型调用提取被反映人信息

        Args:
            case_instruction: 输入的信访件内容

        Returns:
            被反映人信息列表，格式为 [{"mc": "姓名"}]
        """
        try:
            # 根据全局配置选择配置
            if USE_SILICONFLOW:
                base_url = LLM_CONFIG["BASE_URL_dev"]
                model = LLM_CONFIG["MODEL_dev"]
                api_key = LLM_CONFIG.get("API_KEY")
            else:
                base_url = LLM_CONFIG["BASE_URL_1244"]
                model = LLM_CONFIG["MODEL_72B"]
                api_key = None

            print(f"使用配置: {base_url}, 模型: {model}")

            # 调用模型获取被反映人姓名
            if USE_SILICONFLOW and api_key:
                result = quick_chat(
                    base_url=base_url,
                    model=model,
                    system_prompt=get_system_prompt("pc_bfyr_name"),
                    user_prompt=case_instruction,
                    api_key=api_key,
                    temperature=0.5,
                )
            else:
                result = quick_chat(
                    base_url=base_url,
                    model=model,
                    system_prompt=get_system_prompt("pc_bfyr_name"),
                    user_prompt=case_instruction,
                    temperature=0.5,
                )

            # 清洗模型输出，移除think标签和markdown格式
            cleaned_result = clean_llm_result(result.text.strip())
            print(f"模型返回的被反映人信息: {cleaned_result}")

            # 处理返回结果
            return self._process_bfyrs_result(cleaned_result)

        except Exception as e:
            print(f"提取被反映人信息失败: {str(e)}")
            return []

    def _process_bfyrs_result(self, text: str) -> List[Dict[str, str]]:
        """
        处理被反映人信息结果

        Args:
            text: 模型返回的文本

        Returns:
            处理后的被反映人信息列表
        """
        try:
            # 如果返回的是空字符串，返回空列表
            if not text or text.strip() == "":
                return []

            # 按逗号分割姓名
            names = text.split(",")
            result = [{"mc": name.strip()} for name in names if name.strip()]
            return result

        except Exception as e:
            print(f"处理被反映人信息结果失败: {str(e)}")
            return []

    def request_cfj_data(
        self, bh: str, fyrs: str, bfyrs: List[Dict[str, str]]
    ) -> Optional[Dict]:
        """
        请求初次件数据

        Args:
            bh: 信访件编号
            fyrs: 反映人信息
            bfyrs: 被反映人信息列表

        Returns:
            请求结果字典，如果失败返回None
        """
        try:
            # 构建请求数据
            request_data = {"bh": bh, "fyrs": fyrs, "bfyrs": bfyrs}

            print(f"请求初次件数据: {json.dumps(request_data, ensure_ascii=False)}")

            # 发送POST请求
            response = requests.post(
                self.api_url,
                json=request_data,
                timeout=self.timeout,
                headers={"Content-Type": "application/json"},
            )

            response.raise_for_status()
            result = response.json()
            print(f"初次件请求成功: {json.dumps(result, ensure_ascii=False)}")

            return result

        except requests.exceptions.RequestException as e:
            print(f"请求初次件数据失败: {str(e)}")
            # 模拟数据用于测试
            return self._get_mock_cfj_data()
        except Exception as e:
            print(f"处理初次件数据失败: {str(e)}")
            return None

    def _get_mock_cfj_data(self) -> Dict:
        """
        获取模拟的初次件数据（用于测试）

        Returns:
            模拟的初次件数据
        """
        print("使用模拟数据进行测试")
        return {
            "data": [
                {
                    "bh": "XF2024001",
                    "wtxx": {
                        "yjms": "反映李四在2024年1月收受贿赂5万元，利用职务便利为他人谋取利益。",
                        "wtms": "反映李四在2024年1月收受贿赂5万元。",
                    },
                },
                {
                    "bh": "XF2024002",
                    "wtxx": {
                        "yjms": "反映赵六在2024年2月违规操作项目，违反相关规定进行项目审批。",
                        "wtms": "反映赵六在2024年2月违规操作项目。",
                    },
                },
            ]
        }

    def check_duplicate_with_cfj_data(
        self,
        case_instruction: str,
        cfj_data: Union[str, List[Dict]],
        bh: str = "",
        fyrs: str = "",
    ) -> str:
        """
        统一的判重检查函数

        Args:
            case_instruction: 输入的信访件内容
            cfj_data: 初次件数据，可以是JSON字符串或字典列表
            bh: 信访件编号（可选）
            fyrs: 反映人信息（可选）

        Returns:
            判重结果，"1"表示重复，"0"表示不重复
        """
        try:
            print("开始进行初次件判重检查...")

            # 处理初次件数据
            if isinstance(cfj_data, str):
                # 如果是JSON字符串，解析为字典
                try:
                    cfj_list = json.loads(cfj_data)
                except json.JSONDecodeError:
                    print("初次件数据JSON格式错误，按不重复处理")
                    return "0"
            else:
                # 如果不是字符串，直接使用
                cfj_list = cfj_data

            # 统一处理解析后的数据
            print(f"初次件数据类型: {type(cfj_list)}")

            # 如果是字典格式，提取data字段
            if isinstance(cfj_list, dict):
                print(f"初次件数据字典键: {list(cfj_list.keys())}")
                if "data" in cfj_list:
                    cfj_data = cfj_list["data"]  # 提取data字段
                    print(f"data字段类型: {type(cfj_data)}")

                    # 检查data字段是否为字符串（JSON字符串）
                    if isinstance(cfj_data, str):
                        try:
                            cfj = json.loads(cfj_data)  # 解析JSON字符串
                            print(
                                f"解析JSON字符串成功，获取到 {len(cfj) if isinstance(cfj, list) else 1} 条数据"
                            )
                        except json.JSONDecodeError:
                            print("data字段JSON字符串解析失败，按不重复处理")
                            return "0"
                    else:
                        # 如果data字段不是字符串，直接使用
                        cfj = cfj_data
                        print(
                            f"data字段不是字符串，直接使用，获取到 {len(cfj) if isinstance(cfj, list) else 1} 条数据"
                        )

                    if not cfj:
                        print("初次件data字段为空，按不重复处理")
                        return "0"

                    # 如果cfj不是列表格式，将其包装成列表
                    if not isinstance(cfj, list):
                        print(f"初次件数据不是列表格式，将其包装成列表进行处理")
                        cfj = [cfj]
                else:
                    print("未找到data字段，按不重复处理")
                    return "0"
            else:
                # 如果不是字典，直接使用
                cfj = cfj_list

                # 如果cfj不是列表格式，将其包装成列表
                if not isinstance(cfj, list):
                    print(f"初次件数据不是列表格式，将其包装成列表进行处理")
                    cfj = [cfj]

            # 确保是列表格式（双重检查）
            if not isinstance(cfj, list):
                print("初次件数据仍然不是列表格式，按不重复处理")
                return "0"

            if not cfj:
                print("未获取到初次件数据，按不重复处理")
                return "0"

            print(f"获取到 {len(cfj)} 条初次件数据")

            # 限制处理的初次件数量，避免处理过多数据
            max_cfj_to_check = 100  # 最多检查100个初次件
            if len(cfj) > max_cfj_to_check:
                print(f"初次件数量过多({len(cfj)})，只处理前{max_cfj_to_check}个")
                cfj = cfj[:max_cfj_to_check]

            # 直接使用extract_duplicate_check_letters处理初次件数据
            from . import extract_duplicate_check_letters

            # 将初次件数据转换为JSON字符串
            cfj_json = json.dumps(cfj, ensure_ascii=False)

            # 提取初次件内容
            extract_result = extract_duplicate_check_letters(cfj_json)
            cfj_content_list = extract_result.get("result", [])

            if not cfj_content_list:
                print("未能提取到任何初次件内容，按不重复处理")
                return "0"

            print(f"成功提取到 {len(cfj_content_list)} 个初次件内容用于判重检查")

            # 与初次件进行判重比较
            for i, cfj_content in enumerate(cfj_content_list):
                try:
                    # 获取初次件编号
                    cfj_bh = cfj[i].get("bh", f"未知编号_{i+1}")

                    print(
                        f"正在与第 {i+1}/{len(cfj_content_list)} 个初次件 {cfj_bh} 进行判重比较..."
                    )
                    print(f"初次件 {cfj_bh} 提取的对比文本: {cfj_content[:100]}...")

                    # 构建判重内容
                    duplicate_content = f"""
                    当前信访件内容：{case_instruction}
                    
                    初次件内容：{cfj_content}
                    """

                    # 调用判重模型
                    duplicate_result = self._call_duplicate_check_model(
                        duplicate_content
                    )

                    print(f"与初次件 {cfj_bh} 判重结果: {duplicate_result}")

                    # 判断返回结果
                    if duplicate_result == "1":
                        print(f"检测到与初次件 {cfj_bh} 重复，终止检查")
                        return f"1:{cfj_bh}"  # 返回重复结果和编号
                    elif duplicate_result == "0":
                        print(f"与初次件 {cfj_bh} 不重复，继续检查...")
                        continue
                    else:
                        print(
                            f"初次件 {cfj_bh} 返回结果异常: {duplicate_result}，按不重复处理"
                        )
                        continue

                except Exception as e:
                    print(
                        f"与初次件 {cfj_bh if 'cfj_bh' in locals() else f'第{i+1}条'} 判重失败: {str(e)}，按不重复处理"
                    )
                    continue

            print("与所有初次件比较完成，未发现重复")
            return "0"

        except Exception as e:
            print(f"初次件判重检查失败: {str(e)}")
            return "0"

    def _call_duplicate_check_model(self, duplicate_content: str) -> str:
        """
        调用判重模型

        Args:
            duplicate_content: 判重内容

        Returns:
            判重结果，"1"表示重复，"0"表示不重复
        """
        try:
            # 根据全局配置选择配置
            if USE_SILICONFLOW:
                base_url = LLM_CONFIG["BASE_URL_dev"]
                model = LLM_CONFIG["MODEL_dev"]
                api_key = LLM_CONFIG.get("API_KEY")
            else:
                base_url = LLM_CONFIG["BASE_URL_1244"]
                model = LLM_CONFIG["MODEL_72B"]
                api_key = None

            # 调用判重模型
            if USE_SILICONFLOW and api_key:
                result = quick_chat(
                    base_url=base_url,
                    model=model,
                    system_prompt=get_system_prompt("pc"),
                    user_prompt=duplicate_content,
                    api_key=api_key,
                    temperature=0.5,
                )
            else:
                result = quick_chat(
                    base_url=base_url,
                    model=model,
                    system_prompt=get_system_prompt("pc"),
                    user_prompt=duplicate_content,
                    temperature=0.5,
                )

            duplicate_check_result = result.text.strip()
            cleaned_result = clean_llm_result(duplicate_check_result)

            return cleaned_result

        except Exception as e:
            print(f"调用判重模型失败: {str(e)}")
            return "0"

    def check_duplicate_for_network_case(
        self, case_instruction: str, cfj_json: str
    ) -> str:
        """
        网络件判重检查（直接使用传入的初次件数据）

        Args:
            case_instruction: 输入的信访件内容
            cfj_json: 初次件JSON字符串

        Returns:
            判重结果，"1"表示重复，"0"表示不重复
        """
        return self.check_duplicate_with_cfj_data(case_instruction, cfj_json)

    def check_duplicate_for_letter_case(
        self, case_instruction: str, bh: str, fyrs: str = ""
    ) -> str:
        """
        来信件判重检查（需要先获取初次件数据）

        Args:
            case_instruction: 输入的信访件内容
            bh: 信访件编号
            fyrs: 反映人信息（可选）

        Returns:
            判重结果，"1"表示重复，"0"表示不重复
        """
        try:
            # 1. 提取被反映人信息
            bfyrs = self.extract_bfyrs_from_case(case_instruction)
            if not bfyrs:
                print("未提取到被反映人信息，按不重复处理")
                return "0"

            print(f"提取到被反映人: {[bfyr['mc'] for bfyr in bfyrs]}")

            # 2. 请求初次件数据
            cfj_response = self.request_cfj_data(bh, fyrs, bfyrs)
            if not cfj_response:
                print("获取初次件数据失败，按不重复处理")
                return "0"

            # 3. 进行判重检查
            return self.check_duplicate_with_cfj_data(case_instruction, cfj_response)

        except Exception as e:
            print(f"来信件判重检查失败: {str(e)}")
            return "0"


# 创建全局实例
unified_checker = UnifiedDuplicateChecker()


# 异步函数接口
async def check_duplicate_for_network_case(case_instruction: str, cfj_json: str) -> str:
    """网络件判重检查的异步接口"""
    return unified_checker.check_duplicate_for_network_case(case_instruction, cfj_json)


async def check_duplicate_for_letter_case(
    case_instruction: str, bh: str, fyrs: str = ""
) -> str:
    """来信件判重检查的异步接口"""
    return unified_checker.check_duplicate_for_letter_case(case_instruction, bh, fyrs)


# 向后兼容的函数
async def check_cfj_duplicate(
    case_instruction: str, bh: str = "", fyrs: str = ""
) -> str:
    """
    向后兼容的初次件判重函数

    Args:
        case_instruction: 输入的信访件内容
        bh: 信访件编号（可选）
        fyrs: 反映人信息（可选）

    Returns:
        判重结果，"1"表示重复，"0"表示不重复
    """
    if bh:
        # 如果有编号，按来信件处理
        return await check_duplicate_for_letter_case(case_instruction, bh, fyrs)
    else:
        # 如果没有编号，按不重复处理
        return "0"


if __name__ == "__main__":
    # 测试代码
    test_case = "反映李四在2024年3月收受贿赂10万元"

    # 测试网络件判重
    print("=== 测试网络件判重 ===")
    cfj_json = json.dumps(
        {
            "data": [
                {
                    "bh": "XF2024001",
                    "wtxx": {
                        "yjms": "反映李四在2024年1月收受贿赂5万元，利用职务便利为他人谋取利益。",
                        "wtms": "反映李四在2024年1月收受贿赂5万元。",
                    },
                }
            ]
        },
        ensure_ascii=False,
    )

    result1 = unified_checker.check_duplicate_for_network_case(test_case, cfj_json)
    print(f"网络件判重结果: {result1}")

    # 测试来信件判重
    print("\n=== 测试来信件判重 ===")
    result2 = unified_checker.check_duplicate_for_letter_case(
        test_case, "XF2024003", "张三"
    )
    print(f"来信件判重结果: {result2}")
